<?php
/**
 * Dirox Framework
 * Copyright (C) 2005 - 2007 Dirox / Synexser
 * 
 * All rights reserved.
 */

require_once 'Date.php';

class DRX_DateTimeUtils extends Date
{
	/**
	 * Return true if the date given in parameters is in correct mysql format
	 * which is 'YYYY-MM-DD', false otherwise
	 *
	 * @access public
	 * @param string $date_string the date string to validate against mysql date format
	 * @return boolean true if the format is valid, false otherwise
	*/	
	function is_date_sql($date_string)
	{
		$date_array = explode("-",$date_string);
		if (count($date_array) == 3)
		{
			return checkdate($date_array[1],$date_array[2],$date_array[0]);
		}
		return false;
	}

	/**
	 * Return true if the time string given in parameters is in correct mysql format
	 * which is 'H:i:s' or 'H:i', false otherwise
	 *
	 * @access public
	 * @param string the time string to validate against mysql time format
	 * @return boolean true if the format is valid, false otherwise
	*/
	static function is_time_sql($time_string)
	{
		$time_array = explode(':',$time_string);
		if ( count($time_array) >= 2 or count($time_array) <= 3 )
		{
			return 
				// Hour validation
				preg_match('/^[0-2]?[0-9]$/',$time_array[0]) and intval($time_array[0]) <= 24 and
				// Minute validation
				preg_match('/^[0-5]?[0-9]$/',$time_array[1]) and
				// second validation
				( !isset($time_array[2]) or preg_match('/^[0-5]?[0-9]$/',$time_array[2]) );
		}
		return false;
	}

	function date_to_date_sql($date_convert, $format="dd/mm/yyyy")
	{
		$pos = strpos($date_convert, '/');
		if ($pos === false)
			return $date_convert;
		
		switch ($format) {
			case "dd/mm/yyyy":
				list($day, $month, $year) = explode("/", $date_convert);
				break;
			case "mm/dd/yyyy":
				list($month, $day, $year) = explode("/", $date_convert);
				break;
		}

		if (($year == "1970") && ($month == "01" || $month == "1") && ($day == "01" || $day == "1"))
			return "1970-01-01";
		if (checkdate(intval($month), intval($day), intval($year)))
			return date("Y-m-d", mktime(0, 0, 0, intval($month), intval($day), intval($year)));
	
		return $date_convert;
	}
	
	function datetime_to_datetimesql($datetime_convert, $format="dd/mm/yyyy")
	{
		$date = $this->date_to_date_sql(substr($datetime_convert, 0, 10), $format);
		return $date . substr($datetime_convert, 10);
	}
	
	function getDiffTime($time_from, $time_to, $format='dhms')
	{
		$tmp_1=strtotime($time_from);
		$tmp_2=strtotime($time_to);
		$distance=$tmp_2-$tmp_1;
		
		switch ($format) {
			case 'd':
				$day=floor($distance / 86400);
				return "$day d";
				break;
			case 'h':
				$hour=floor($distance / 3600 );
				return "$hour h";
				break;
			case 'm':
				$min=floor($distance / 60 );
				return "$min m";
				break;
			case 's':
				return "$distance s";
				break;
			case 'array':
			case 'dhms':
			default:
				$day=floor($distance / 86400);
				$distance=$distance % 86400;
				$hour=floor($distance / 3600 );
				$distance=$distance % 3600;
				$min=floor($distance / 60 );
				$s=$distance % 60;
				
				if ($format == 'array')	{
					return array("d" => $day, "h" => $hour, "m" => $min, "s" => $s);
				} else {
					return "$day d $hour h $min m $s s";
				}
		}
	}
	
	/**
     * Get a string (or other) representation of the date
     *
     * Get a string (or other) representation of this date in the
     * format specified by the DATE_FORMAT_* constants.
     *
     * @access public
     * @param int $format format constant (DATE_FORMAT_*) of the output date
     * @return string the date in the requested format
     */
    function getDate($format = DATE_FORMAT_ISO)
    {
        switch ($format) {
	        case DATE_FORMAT_ISO:
	            return $this->format("%Y-%m-%d %T");
	            break;
	        case DATE_FORMAT_ISO_BASIC:
	            $format = "%Y%m%dT%H%M%S";
	            if ($this->tz->getID() == 'UTC') {
	                $format .= "Z";
	            }
	            return $this->format($format);
	            break;
	        case DATE_FORMAT_ISO_EXTENDED:
	            $format = "%Y-%m-%dT%H:%M:%S";
	            if ($this->tz->getID() == 'UTC') {
	                $format .= "Z";
	            }
	            return $this->format($format);
	            break;
	        case DATE_FORMAT_ISO_EXTENDED_MICROTIME:
	            $format = "%Y-%m-%dT%H:%M:%s";
	            if ($this->tz->getID() == 'UTC') {
	                $format .= "Z";
	            }
	            return $this->format($format);
	            break;
	        case DATE_FORMAT_TIMESTAMP:
	            return $this->format("%Y%m%d%H%M%S");
	            break;
	        case DATE_FORMAT_UNIXTIME:
	            return mktime($this->hour, $this->minute, $this->second, $this->month, $this->day, $this->year);
	            break;
	        default:
	        	return $this->format($format);
		}
	}

	public function parseDate($date_str,$format)
	{
		// Transform the format string in a pregexp
		$preg_format = preg_replace(
			array(
				'/[\(\)\{\}\[\]\?\.\*\+\/\\\\]/', // special regexp characters
				'/d/', // day of month with leading 0
				'/j/', // day of month without leading 0
				'/[mh]/', // month with leading 0 and 12-hour format of an hour with leading zeros
				'/[ng]/', // month without leading 0 and 12-hour format of an hour without leading zeros
				'/Y/', // year on 4 digit
				'/y/', // year on 2 digit
				'/[is]/', // minute and second with leading 0
				'/G/', // 24-hour format of an hour without leading zeros
				'/H/', // 24-hour format of an hour with leading zeros
				'/a/', // Lowercase Ante meridiem and Post meridiem
				'/A/' // Uppercase Ante meridiem and Post meridiem
				),
			array(
				'\\\\$0', // special regexp characters
				'([0-3]\d)', // day of month with leading 0
				'([1-3]?\d)', // day of month without leading 0
				'([0-1]\d)', // month with leading 0 and 12-hour format of an hour with leading zeros
				'(1?\d)', // month without leading 0 and 12-hour format of an hour without leading zeros
				'(\d{4,})', // year on 4 digit
				'(\d{2})', // year on 2 digit
				'([0-5]\d)', // minute and second with leading 0
				'([1-2]?\d)', // 24-hour format of an hour without leading zeros
				'([0-2]\d)', // 24-hour format of an hour with leading zeros
				'([ap]m)', // Lowercase Ante meridiem and Post meridiem
				'([AP]M)' // Uppercase Ante meridiem and Post meridiem
				),
			$format);

		// We get the list of format modifier in a simple matches array
		$count = preg_match_all('/[djmhngYyisGHaA]/',$format,$modifiers);
		// If the format contains no modifiers, we return an empty array
		if ($count == 0)
		{
			return array();
		}
		
		$count = preg_match_all('/'.$preg_format.'/',$date_str,$matches);
		// If there's no match, we know the date is in an invalid format, we return FALSE
		if ($count == 0)
		{
			return FALSE;
		}

		// Match modifier with their values
		$format_arr = array();
		$index = 1;
		foreach($modifiers[0] as $modifier)
		{
			if ($modifier == 'A')
			{
				$format_arr['a'] = strtolower($matches[$index][0]);
			}
			else
			{
				$format_arr[$modifier] = $matches[$index][0];
			}
			++$index;
		}
		
		// Construct the date structure
		$date = array('year' => 1900, 'month' => 1, 'day' => 1, 'hour' => 0, 'minute' => 0, 'second' => 0);

		foreach($format_arr as $mod => $val)
		{
			$val = intval($val);
			switch($mod)
			{
				case 'y' :
					$date['year'] = 1900+$val;
					if ($val < 70)
					{
						$date['year'] += 100;
					}
					break;
				case 'Y' :
					$date['year'] = $val;
					break;
				case 'm' :
				case 'n' :
					$date['month'] = $val;
					break;
				case 'd' :
				case 'j' :
					$date['day'] = $val;
					break;
				case 'i' :
					$date['minute'] = $val;
					break;
				case 's' :
					$date['second'] = $val;
					break;
				case 'g' :
				case 'h' :
					$hour = $val;
					if ($hour >= 1 and $hour <= 12)
					{
						$hour %= $hour;
						if (isset($format_arr['a']) and $format_arr['a'] == 'pm')
						{
							$hour += 12; 
						}
						$date['hour'] = $hour;
					}
					else
					{
						return FALSE;
					}
					break;
				case 'G' :
				case 'H' :
					$hour = $val;
					if ($hour >= 0 and $hour <= 23)
					{
						$date['hour'] = $hour;
					}
					else
					{
						return FALSE;
					}
					break;
				default :
					break;
			}
		}

		// Now validate the structure, then return it if it's ok
		if (checkdate($date['month'],$date['day'],$date['year']))
		{
			return $date;
		}
		else
		{
			return FALSE;
		}
	}

	public function formatDate($date,$format)
	{
		// Construct the date structure
		$date_new = array('year' => 1900, 'month' => 1, 'day' => 1, 'hour' => 0, 'minute' => 0, 'second' => 0);
		$date = array_merge($date_new,$date);
		$date['d'] = str_pad(strval($date['day']),2,'0',STR_PAD_LEFT);
		$date['m'] = str_pad(strval($date['month']),2,'0',STR_PAD_LEFT);
		$date['Y'] = str_pad(strval($date['year']),4,'0',STR_PAD_LEFT);
		if ($date['year'] >= 1970 and $date['year'] <= 1999)
		{
			$date['y'] = strval($date['year'] - 1900);
		}
		elseif ($date['year'] >= 2000 and $date['year'] <= 2069)
		{
			$date['y'] = str_pad(strval($date['year'] - 2000),2,'0',STR_PAD_LEFT);
		}
		else
		{
			$date['y'] = '70';
		}
		$date['a'] = ($date['hour'] < 12 ? 'am' : 'pm' );
		$date['A'] = strtoupper($date['a']);
		if ($date['hour'] >= 12)
		{
			$date['g'] = $date['hour'] - 12;
		}
		else
		{
			$date['g'] = $date['hour'];
		}
		if ($date['g'] == 0)
		{
			$date['g'] = '12';
		}

		$date['h'] = str_pad($date['g'],2,'0',STR_PAD_LEFT);
		$date['H'] = str_pad(strval($date['hour']),2,'0',STR_PAD_LEFT);
		$date['i'] = str_pad(strval($date['minute']),2,'0',STR_PAD_LEFT);
		$date['s'] = str_pad(strval($date['second']),2,'0',STR_PAD_LEFT);

		return str_replace(array('d','j','m','n','Y','y','a','A','g','h','G','H','i','s'),
			array($date['d'],$date['day'],$date['m'],$date['month'],$date['Y'],
				$date['y'],$date['a'],$date['A'],$date['g'],$date['h'],
				$date['hour'],$date['H'],$date['i'],$date['s']),
			$format);
	}
	
	function convertDateToDisplayStyle($date, $french_type = true)
    {
        if( preg_match('/[\/-]/', $date) )
        {
        if ($date == '') return '';
        list($year, $month, $day) = preg_split('/[\/-]/', $date);
        $tmp_date = mktime(0, 0, 0, intval($month) , intval($day) , intval($year));
        }
        else
        {
        	$tmp_date = $date;
        }

        if ($french_type)
        {
            return date('d/m/Y', $tmp_date);

        }
        return date('m/d/Y', $tmp_date);

    }
    
    /* BEGIN - Moved from DRX_Utils */
	function addDay($day, $date = "", $format = "Y-m-d")
    {
        if ($date == "") $date = date("Y-m-d");
        $time = strtotime($date);
        $addTime = mktime(0, 0, 0, date("m", $time) , $day+date("d", $time) , date("Y", $time));
        return date($format, $addTime);

    }
    
}